package com.qinglei.recoup.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qinglei.recoup.common.domain.Tree;
import com.qinglei.recoup.common.utils.DateUtil;
import com.qinglei.recoup.common.utils.JsonUtils;
import com.qinglei.recoup.common.utils.RecoupUtil;
import com.qinglei.recoup.system.dao.EventLogMapper;
import com.qinglei.recoup.system.domain.*;
import com.qinglei.recoup.system.enums.EventEnum;
import com.qinglei.recoup.system.manager.DictManager;
import com.qinglei.recoup.system.pojo.DeanBedVO;
import com.qinglei.recoup.system.pojo.EventLogVO;
import com.qinglei.recoup.system.pojo.PageParam;
import com.qinglei.recoup.system.pojo.SearchEventParam;
import com.qinglei.recoup.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EventLogServiceV1 {

    @Resource
    private DictManager dictManager;

    @Resource
    private DeanBedService deanBedService;

    @Resource
    private BedService bedService;

    @Resource
    private EventLogService eventLogService;

    @Resource
    private EventLogMapper  eventLogMapper;

    @Resource
    private NurseBedService nurseBedService;


    public IPage<EventLogVO> searchEvent(SearchEventParam param, PageParam pageParam) {
        // 处理事件类型筛选项
        Set<Integer> typeBedIds = new HashSet<>();
        Set<Integer> typeNurseIds = new HashSet<>();
        boolean isAllType = false;
        if (StringUtils.isNotEmpty(param.getTypeIds())) {
            if (param.getTypeIds().equals("0")) {
                // 事件类型未选中
                return new Page<>();
            } else {
                // 事件类型选择个别
                List<Integer> listFilter = Arrays.stream(param.getTypeIds().split(","))
                        .map(Integer::valueOf).collect(Collectors.toList());
                for (Integer filterType : listFilter) {
                    DictBO dict = dictManager.getDictItem(EventServiceImpl.DICT_EVENT_FILTER_TYPE, (long) filterType);
                    if (dict != null) {
                        List<Integer> eventTypeIds = JsonUtils.jsonToList(dict.getOtherVal(), Integer.class);
                        if (CollectionUtils.isNotEmpty(eventTypeIds)) {
                            if (filterType == EventServiceImpl.EVENT_FILTER_TYPE_TOUR
                                    || filterType == EventServiceImpl.EVENT_FILTER_TYPE_CHANGE_SHIFTS) {
                                // 巡视或者交接班
                                typeBedIds.addAll(eventTypeIds);
                            } else {
                                // 床位相关
                                typeBedIds.addAll(eventTypeIds);
                            }
                        }
                    }
                }
            }
        } else {
            // 全部事件类型
            isAllType = true;
        }
        String bedIdsStr = param.getBedIds();
        String[] bedIdss = null;
        Set<Integer> bedIds = new HashSet<>();
        if (!StringUtils.isEmpty(bedIdsStr)){
            bedIdss= bedIdsStr.split(",");
        }
        if(bedIdss!=null){
            for (int i=0;i<bedIdss.length;i++){
                bedIds.add(Integer.parseInt(bedIdss[i]));
            }
        }

        User user = RecoupUtil.getCurrentUser();
        List<DeanBed> deanBedList =  deanBedService.list(Wrappers.<DeanBed>lambdaQuery().eq(DeanBed::getUserId, user.getId()));
        if(bedIds==null || bedIds.size()==0){
            Set<Integer> bedIdsTmp = getBedSetDean(deanBedList);
            Set<Integer> bedIdResult = new HashSet<>();
            bedIdsTmp.forEach(b->{
                QueryWrapper bedWrapper = new QueryWrapper();
                bedWrapper.eq("id",b);
                bedWrapper.eq("is_deleted",0);
                Bed bed = bedService.getBaseMapper().selectOne(bedWrapper);
                if(bed!=null){
                    bedIdResult.add(b);
                }
            });
            bedIds.addAll(bedIdResult);
        }
        System.err.println(bedIds);
        QueryWrapper nurseBedWrapper = new QueryWrapper();
        if(bedIds.size()>0){
            nurseBedWrapper.in("bed_id", bedIds);
        }
        List<NurseBed>  nurseBedList =  nurseBedService.getBaseMapper().selectList(nurseBedWrapper);
        Set<Long> userIds = new HashSet<>();
        userIds.add(user.getId());
        nurseBedList.forEach(nurseBed->{
            userIds.add(nurseBed.getUserId());
        });

        LambdaQueryWrapper<EventLog> wrapper = Wrappers.lambdaQuery();



        if(typeBedIds.size()>0){
            wrapper.in(EventLog::getType, typeBedIds);
        }
        Set<Integer> finalBedIds = bedIds;
//        wrapper.and(i -> i.in(EventLog::getBedId, finalBedIds)
//                .or(j -> j.in(EventLog::getUserId, userIds)));
        wrapper.and(i -> i.in(EventLog::getBedId, finalBedIds)
                .or(j -> j.and(
                        k -> k.in(EventLog::getUserId, userIds).and(s->s.in(EventLog::getEventId,0))
                )));
        LocalDate startDate = LocalDate.parse(param.getStartDate());
        LocalDate endDate = LocalDate.parse(param.getEndDate()).plusDays(1);
        wrapper.between(EventLog::getCreateTime, startDate, endDate).orderByDesc(EventLog::getId);
        Page<EventLog> eventLogPage = new Page<>();
        eventLogPage.setCurrent(pageParam.getPageNum());
        eventLogPage.setSize(pageParam.getPageSize());
        IPage<EventLog> eventLogIPage = eventLogService.getBaseMapper().selectPage(eventLogPage, wrapper);
        List<EventLog> eventLogs = eventLogIPage.getRecords();
        List<EventLogVO> eventLogVOS = eventLogs.stream().map(eventLog -> {
            EventLogVO eventLogVO = new EventLogVO();
            eventLogVO.setName(eventLog.getName());
            eventLogVO.setEvtLogId(eventLog.getId());
            eventLogVO.setContent(eventLog.getContent());
            eventLogVO.setTime(DateUtil.formatFullTime(eventLog.getCreateTime(), DateUtil.FULL_TIME_CHS_PATTERN));
            // 设置是否报警
            if (eventLog.getTypeGroup() == EventEnum.TYPE_ALARM) {
                eventLogVO.setIsAlarm(1);
            }
            // 设置是否突出显示
            Integer type = eventLog.getType();
            EventEnum eventEnum = EventEnum.getByCode(type);
            if(eventEnum!=null){
                boolean  isStress =  eventEnum.isStress();
                if (isStress) {
                    eventLogVO.setIsStress(1);
                }
            }
            return eventLogVO;
        }).collect(Collectors.toList());
        Page<EventLogVO> eventLogVOPage = new Page<>();
        eventLogVOPage.setTotal(eventLogIPage.getTotal());
        eventLogVOPage.setSize(eventLogIPage.getSize());
        eventLogVOPage.setCurrent(eventLogIPage.getCurrent());
        eventLogVOPage.setRecords(eventLogVOS);
        return eventLogVOPage;
    }


    /**
     * 查询所有和当前用户有关系的床位
     * @param deanBedList
     * @return
     */
    public Set<Integer> getBedSetDean(List<DeanBed> deanBedList ) {
        Set<Integer> bedIds = new HashSet<>();
        Set<Integer> roomIds = new HashSet<>();
        Set<Integer> floorIds = new HashSet<>();
        Set<Integer> buildingIds = new HashSet<>();
        boolean hasTotal = false;
        for (DeanBed deanBed : deanBedList) {
            switch (deanBed.getType()) {
                case BedService.TYPE_ROOT:
                    hasTotal = true;
                    break;
                case BedService.TYPE_BUILDING:
                    buildingIds.add(deanBed.getObjId());
                    break;
                case BedService.TYPE_FLOOR:
                    floorIds.add(deanBed.getObjId());
                    break;
                case BedService.TYPE_ROOM:
                    roomIds.add(deanBed.getObjId());
                    break;
                case BedService.TYPE_BED:
                    bedIds.add(deanBed.getObjId());
                    break;
            }
        }
        roomIds.forEach(roomId->{
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("room_id",roomId);
            queryWrapper.eq("is_deleted",0);
            List<Bed> beds  = bedService.list(queryWrapper);
            if (beds!=null){
                beds.forEach(bed -> {
                    bedIds.add(bed.getId());
                });
            }

        });

        floorIds.forEach(floorId->{
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("floor_id",floorId);
            queryWrapper.eq("is_deleted",0);
            List<Bed> beds  = bedService.list(queryWrapper);
            if (beds!=null){
                beds.forEach(bed -> {
                    bedIds.add(bed.getId());
                });
            }
        });

        buildingIds.forEach(buildingId->{
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("building_id",buildingId);
            queryWrapper.eq("is_deleted",0);
            List<Bed> beds  = bedService.list(queryWrapper);
            if (beds!=null){
                beds.forEach(bed -> {
                    bedIds.add(bed.getId());
                });
            }
        });

        if(hasTotal){
            QueryWrapper queryWrapperB = new QueryWrapper();
            queryWrapperB.eq("tenant_id",RecoupUtil.getCurrentUser().getTenantId());
            queryWrapperB.eq("is_deleted",0);
            List<Bed> bedsList = bedService.getBaseMapper().selectList(queryWrapperB);
            bedsList.forEach(bed->{
                bedIds.add(bed.getId());
            });

        }

        return bedIds;
    }

}
